'''
Created on Nov 4, 2009

@author: wangjo
'''
from google.appengine.ext import webapp
from google.appengine.api.labs import taskqueue
from google.appengine.api import users
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import memcache
import os
import logging
import spider
import rss
import math
import api
import mokomodel
import utility
import templatefilters

MAX_PER_PAGE = 4*6

class IndexPage(utility.BaseRequestHandler):
    def get(self):
        cache = memcache.Client()
        page = self.pageHandler()
        offset = (page-1)*MAX_PER_PAGE
        models = cache.get(str(page), utility.CACHE_NS_GALLERY_WEB)
        if not models:
            models = mokomodel.model.get_topgirls(MAX_PER_PAGE, offset)
            cache.set(str(page), models, time=utility.CACHE_DURATION, namespace = utility.CACHE_NS_GALLERY_WEB)
            logging.info('set cache for page:%d'%page)
        else:
            logging.info('load from cache')
        count = cache.get('count', utility.CACHE_NS_GALLERY_WEB)
        if not count:
            count = mokomodel.model.get_topgirl_count()
            cache.set('count', count, time=utility.CACHE_DURATION, namespace = utility.CACHE_NS_GALLERY_WEB)
        model_count = cache.get('totalcount', utility.CACHE_NS_GALLERY_WEB)
        if not model_count:
            model_count = mokomodel.model.get_model_count()
            cache.set('totalcount', model_count, time=utility.CACHE_DURATION, namespace = utility.CACHE_NS_GALLERY_WEB)
        pages = int(math.ceil(count/float(MAX_PER_PAGE)))
        prev = False
        if page > 1:
            prev = page -1
        next = False
        if page < pages:
            next = page + 1
        logging.info('next:%s'%next)
        
        self.generate('moko.html', {
                      'application_name' : 'MOKO Top Girl',
                      'models': models,
                      'pages': range(1, pages+1),
                      'page': page,
                      'count': count,
                      'prev': prev,
                      'next': next,
                      'model_count': model_count,
                })
        
class SpiderPage(utility.BaseRequestHandler):
    def get(self):
        homepromo = 'http://www.moko.cc/moko_post_ent/moko_post_index/%d/postTJ.html'
        pages = range(1, 11)
        for p in pages:
            url = homepromo%p
            taskqueue.add(url='/task/grid', params={'grid': url}, method='GET')
            
class GalleryPage(utility.BaseRequestHandler):
    def get(self):
        page = self.pageHandler()
        offset = (page -1)*MAX_PER_PAGE
        #list all the gallerys
        albums = mokomodel.album.get_albums(MAX_PER_PAGE, offset)
        count = mokomodel.album.get_album_count()
        pages = int(math.ceil(count/float(MAX_PER_PAGE)))
        self.generate('gallery.html', {
                          'application_name' : 'MOKO Top Girl',
                          'albums': albums,
                          'pages': range(1, pages+1),
                          'page': page,
                          'count': count,
                })

class ModelPage(utility.BaseRequestHandler):
    def get(self, username):
        if not username:
            self.redirect('/')
        cache = memcache.Client()
        if users.is_current_user_admin():
            m = mokomodel.model.get_model(username)
        else:
            m = cache.get(username, utility.CACHE_NS_MODEL)
            if not m:
                m = mokomodel.model.get_model(username)
                if m:
                    cache.set(username, m, time=utility.CACHE_DURATION, namespace=utility.CACHE_NS_MODEL)
        if not m:
            logging.error('not found model:%s'%username)
            self.error(404)
        else:
            if users.is_current_user_admin():
                action = self.request.get('action', None)
                if action:
                    action = action.lower()
                    if action == 'update':
                        spider.update_model(username)
                    elif action == 'excluded':
                        m.excluded = True
                        m.put()
                    elif action == 'mokogirl':
                        m.gender = False
                        m.put()
                
            navlinks = {}
            navlinks['/'] = 'Home'
            if users.is_current_user_admin():
                taskqueue.add(url='/task/gallery', params={'model': m.username}, method='GET')
            #photos = m.get_photos()
            albumkey = "album_%s"%username
            if users.is_current_user_admin():
                albums = m.get_albums()
            else:
                albums = cache.get(albumkey, utility.CACHE_NS_MODEL)
                if not albums:
                    albums = m.get_albums()
                    if albums:
                        cache.set(albumkey, albums, time=utility.CACHE_DURATION, namespace = utility.CACHE_NS_MODEL)
            self.generate('model.html', {'navlinks': navlinks,
                                         'model': m,
                                         'albums': albums,})
class AlbumPage(utility.BaseRequestHandler):
    def get(self, albumkey):
        if not albumkey: self.redirect('/')
        cache = memcache.Client()
        index = self.indexHandler()
        if users.is_current_user_admin():
            album = mokomodel.album.get(albumkey)
            if album:
                cache.set(albumkey, album, time=utility.CACHE_DURATION , namespace = utility.CACHE_NS_ALBUM)
        else:
            album = cache.get(albumkey, utility.CACHE_NS_ALBUM)
            if not album:
                album = mokomodel.album.get(albumkey)
                if album:
                    cache.set(albumkey, album, time=utility.CACHE_DURATION , namespace = utility.CACHE_NS_ALBUM)
        if album:
            if users.is_current_user_admin():
                action = self.request.get('action',None)
                if action:
                    action = action.lower()
                    if action=='verify':
                        mokomodel.cronlog.add_verify_album(album, True)
                    elif action == 'excluded':
                        album.excluded = True
                        album.put()
                    elif action == 'mtg':
                        album.mtgalbum = True
                        album.put()
                    elif action == 'selected':
                        album.selected = True
                        album.put()
                    elif action == 'delete':
                        album.delete()
                        return self.error(403)
                        
            navlinks = {}
            navlinks['/'] = 'Home'
            navlinks['/model/%s'%album.model.username] = album.model.name
            if users.is_current_user_admin():
                taskqueue.add(url='/task/album', params={'album': album.url}, method='GET')
            photos = None
            photo = None
            pp = None
            np = None
            photokey = "photo_%s"%albumkey
            if users.is_current_user_admin():
                qr = album.get_photos()
                if qr:
                    cache.set(photokey, qr, time=utility.CACHE_DURATION, namespace = utility.CACHE_NS_ALBUM)
            else:
                qr = cache.get(photokey, utility.CACHE_NS_ALBUM)
                if not qr:
                    qr = album.get_photos()
                    if qr:
                        cache.set(photokey, qr, time=utility.CACHE_DURATION, namespace = utility.CACHE_NS_ALBUM)
            if qr:
                photos = []
                if getattr(qr, '__iter__', False):
                    photos = qr
                else:
                    photos.append(qr)
            if photos:
                if index > len(photos):
                    index = len(photos)
                photo = photos[index-1]
                if index > 1:
                    pp = photos[index-2]
                if index < len(photos):
                    np = photos[index]
            self.generate('album.html', { 'navlinks':navlinks, 
                                          'album': album, 
                                          'photos':photos,
                                          'photo':photo, 
                                          'next':np, 
                                          'prev':pp,
                                          'index': index, 
                                          'ni':index+1, 
                                          'pi':index-1,})
        else:
            logging.error('Invalid album key:%s'%albumkey)
            self.error(403)
    
    def indexHandler(self):
        index = self.request.get('index', None)
        if not index or int(index) < 1:
            index = 1
        else:
            index = int(index)
        return index

class ApiPage(utility.MultipleOutputRequestHandler):
    _ACTION_MAP = {
                   'default':   'modelAction',
                   'photo':     'photoAction',
                   'album':     'albumAction',
                   'model':     'modelAction',
                   }
    def get(self, target):
        actionName = ApiPage._ACTION_MAP['default']
        action = None
        if not target:
            action = getattr(self, actionName)
        else:
            target = target.lower()
            if target in ApiPage._ACTION_MAP:
                actionName = ApiPage._ACTION_MAP[target]
            action = getattr(self, actionName)
        if action:
            action()
    
    def photoAction(self):
        logging.info('photo action')
    def albumAction(self):
        logging.info('album action')
    def modelAction(self):
        lastkey = self.request.get('last', None)
        models = mokomodel.model.get_topgirls_from(MAX_PER_PAGE, lastkey)
        next = True
        if len(models) < MAX_PER_PAGE:
            next = False
        last = models[len(models)-1]
        #logging.info(json.dumps(last))
        self.multiplegen('api.model', {'models': models,'last':last, 'next':next,})

class TaskPage(webapp.RequestHandler):
    _ACTION_MAP = {
                   'default':   'modelAction',
                   'album':     'albumAction',
                   'model':     'modelAction',
                   'gallery':   'galleryAction',
                   'grid':      'gridAction',
                   'filteralbum': 'filteralbumAction',
                   'filtermodel': 'filtermodelAction',
                   'reloadalbum': 'reloadAction',
                   }
    def get(self, target):
        logging.info('task target:%s'%target)
        actionName = TaskPage._ACTION_MAP['default']
        action = None
        if not target:
            action = getattr(self, actionName)
        else:
            target = target.lower()
            if target in TaskPage._ACTION_MAP:
                actionName = TaskPage._ACTION_MAP[target]
            action = getattr(self, actionName)
        if action:
            action()
    def filteralbumAction(self):
        albumkey = self.request.get('album', None)
        if albumkey:
            album = mokomodel.album.get(albumkey)
            if album:
                    logging.info('start filtering album:%s'%album.url)
                    iphotos = album.get_photos_iphone()
                    photos = album.get_filtering_photos()
                    dic_iphotos = {}
                    for photo in iphotos:
                        name = templatefilters.imagename(photo.url)
                        dic_iphotos[name] = photo
                    for photo in photos:
                        if photo.tag == spider.TAG_COVER:
                            photo.iphone = False
                            photo.put()
                        elif photo.url == album.cover:
                            photo.iphone = False
                            photo.put()
                        else:
                            name = templatefilters.imagename(photo.url)
                            if not name in dic_iphotos.keys():
                                photo.iphone = True
                                dic_iphotos[name] = photo
                                photo.put()
                    album.filtered = True
                    album.put()
                    logging.info('filter album finished:%s'%album.url)
            else:
                logging.info('album has been filtered already:%s'%album.url)
    def reloadAction(self):
        albumkey = self.request.get('album', None)
        if albumkey:
            album = mokomodel.album.get(albumkey)
            if album:
                photos = album.get_photos()
                for photo in photos:
                    mokomodel.reload_transcation(photo)
                    
    def filtermodelAction(self):
        modelname = self.request.get('model', None)
        if modelname:
            model = mokomodel.model.get_model(modelname)
            if model:
                albums = model.get_albums_unfiltered()
                if albums and len(albums) > 0:
                    for album in albums:
                        key = album.key()
                        logging.info('start filter album with key:%s'%key)
                        taskqueue.add(url='/task/filteralbum', params={'album':key}, method='GET')
                        
        return False;
    def modelAction(self):
        cache = memcache.Client()
        modelname = self.request.get('model', None)
        if modelname:
            logging.info('model task:%s'%modelname)
            m = spider.update_model(modelname)
            if m:
                cache.set(modelname, m, time=utility.CACHE_DURATION , namespace = utility.CACHE_NS_MODEL)
                
    def albumAction(self):
        albumurl = self.request.get('album', None)
        logging.info('start fetch album:%s'%albumurl)
        spider.fetch_album(albumurl) 
        
    def gridAction(self):
        gridurl = self.request.get('grid', None)
        if gridurl:
            logging.info('start fetch grid:%s'%gridurl)
            spider.fetch_grids(gridurl)
            
    def galleryAction(self):
        modelname = self.request.get('model', None)
        logging.info('gallery task:%s'%modelname)
        if not modelname:
            self.redirect('/spider')
        else:
            spider.fetch_gallery(modelname)
    
class PhotoPage(utility.MultipleOutputRequestHandler):
    def get(self):
        page = self.pageHandler()
        offset = (page -1)*MAX_PER_PAGE
        photos = mokomodel.cronlog.get_non_downloaded_photos(MAX_PER_PAGE, offset)
        if not photos or len(photos) == 0:
            self.error(403)
            return 
        if len(photos) > 0:
            updated = max([p.updated for p in photos])
        else:
            updated = None
        lphoto = photos[len(photos)-1]
        #self.response.headers['Content-Type'] = output_type[0]
        self.multiplegen('photo', {
                    'photos': photos,
                    'lphoto': lphoto,
                    'updated': updated,})
class LogPage(utility.BaseRequestHandler):
    def get(self, target):
        if not target: return self.error(403)
        key = self.request.get('id')
        target = target.strip().lower()
        if target == 'photo':
            p = mokomodel.cronlog.add_download_photo(key, True)
            if p:
                self.response.out.write('load image log successful: %s'%p.url)
            else:
                self.response.out.write('load image log failed')
        else:
            self.response.out.write('unknown target')  

class RSSHomePage(utility.BaseRequestHandler):
    def get(self):
        self.response.out.write('This is:%s'%self.request.host)  

class LocalSpiderPage(utility.BaseRequestHandler):
    def get(self):
        s = spider.spider()
        s.crawler('http://www.moko.cc/post_ent_mvp_svp/1/postList.html', mokomodel.model, False) 
        
class CategoriesPage(utility.BaseRequestHandler):
    def get(self):
        categories = mokomodel.category.get_categories()
        self.generate('categories.html', {'categories': categories},)
        
class CategoryPage(utility.BaseRequestHandler):
    def get(self, catid):
        if not catid: return self.error(404)
        cat = mokomodel.category.get(catid)
        if not cat:
            return self.error(404)
        page = self.pageHandler()
        offset = (page-1)*MAX_PER_PAGE
        count = cat.get_model_count()
        pages = int(math.ceil(count/float(MAX_PER_PAGE)))
        prev = False
        if page > 1:
            prev = page -1
        next = False
        if page < pages:
            next = page + 1
        models = cat.get_models(MAX_PER_PAGE, offset)
        self.generate('category.html', {
                      'application_name' : 'MOKO Top Girl',
                      'models': models,
                      'pages': range(1, pages+1),
                      'page': page,
                      'count': count,
                      'prev': prev,
                      'next': next,
                })

mainApplication = webapp.WSGIApplication([
            ('/localspider.*', LocalSpiderPage),
            ('/spider.*', SpiderPage),
            ('/categories.*', CategoriesPage),
            (r'/category/(.*)', CategoryPage),
            ('/gallery.*', GalleryPage),
            (r'/model/(.*)', ModelPage),
            (r'/api/(.*)', ApiPage),
            ('/photo.*', PhotoPage),
            (r'/album/(.*)', AlbumPage),
            (r'/task/(.*)', TaskPage),
            (r'/log/(.*)', LogPage),
            ('/.*', IndexPage)
            ], debug=utility.DEBUG)

rssApplication = webapp.WSGIApplication([('/models.*', rss.ModelsPage),
                                         ('/free.*', rss.FreePage),
                                         ('/categorylist.*', rss.CategoryListPage),
                                         (r'/model/(.*)', rss.ModelPage),
                                         (r'/category/(.*)', rss.CategoryPage),
                                         (r'/album/(.*)', rss.AlbumPage),
                                         ('/.*', rss.ModelsPage)], debug= utility.DEBUG)

apiApplication = webapp.WSGIApplication([('/gallery.*', api.galleryHandler), 
                                         ('/.*', api.homeHandler)], debug=utility.DEBUG)

applications = {
  'mtopgirl.appspot.com': mainApplication,
  'localhost':mainApplication,
  'mtg.taobility.com':mainApplication,
  'mtgrss.taobility.com':rssApplication,
  'itopgirl.taobility.com':mainApplication,
  'itopgirlrss.taobility.com':rssApplication,
  'rss.mtopgirl.appspot.com': rssApplication,
  'api.mtopgirl.appspot.com': apiApplication,
}
       
def main():
    run_wsgi_app(applications[os.environ['SERVER_NAME']])

if __name__ == "__main__":
    main()        